package csc.fresher.view;

import java.io.IOException;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import csc.fresher.commons.BankingConstant;
import csc.fresher.entity.Customer;
import csc.fresher.entity.CustomerAccount;
import csc.fresher.entity.DepositAccount;
import csc.fresher.entity.DepositTransaction;
import csc.fresher.entity.SystemUser;
import csc.fresher.entity.TransactionState;
import csc.fresher.entity.TransactionType;
import csc.fresher.service.AccountService;
import csc.fresher.service.DepositAccountService;
import csc.fresher.service.DepositAccountTransactionService;
import csc.fresher.service.SystemUserService;

@Component
@Scope(value = "session")
public class PendingTransactionManageBean {
	@Autowired
	private DepositAccountTransactionService depositAccountTransactionService;
	@Autowired
	private DepositAccountService depositAccountService;
	@Autowired
	private AccountService accountService;
	@Autowired
	private SystemLoginManageBean systemLoginManageBean;
	@Autowired
	private SystemUserService systemUserService;

	private List<DepositTransaction> listPendingTransactions;
	private DepositTransaction transactionSelected = null;
	private DepositTransaction transactionRelated = null;
	private DepositAccount sender = null;
	private DepositAccount receiver = null;
	private SystemUser systemUser;

	public void onLoad() {

		if (systemLoginManageBean.getSystemUser() == null) {
			try {
				FacesContext.getCurrentInstance().getExternalContext()
						.redirect("/csc_final/templates3/Logon.jsf");
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			systemUser = systemLoginManageBean.getSystemUser();
			List<Long> listrole = systemUserService
					.getRoleByUserName(systemUser.getUserName());
			boolean result = checkRole(listrole);
			if (result == false) {
				try {
					FacesContext.getCurrentInstance().getExternalContext().redirect("/csc_final/Group1/AccountManagement.xhtml");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public boolean checkRole(List<Long> listRole) {

		for (int i = 0; i < listRole.size(); i++) {
			if (BankingConstant.ROLE_ACCOUNT_ADMIN == listRole.get(i)) {
				return true;
			}
		}
		return false;
	}

	public void setDepositAccountTransactionService(
			DepositAccountTransactionService depositAccountTransactionService) {
		this.depositAccountTransactionService = depositAccountTransactionService;
	}

	public void setDepositAccountService(
			DepositAccountService depositAccountService) {
		this.depositAccountService = depositAccountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	public DepositAccount getSender() {
		try {
			long senderDepositNumber = transactionSelected.getSenderID();
			sender = depositAccountService
					.getDepositAccountByDepositAccountID(senderDepositNumber);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return sender;
	}

	public DepositAccount getReceiver() {
		receiver = null;
		if ((!transactionSelected.getTransactionType().equals(
				TransactionType.WITHDRAW))
				&& (!transactionSelected.getTransactionType().equals(
						TransactionType.DEPOSIT))) {

			try {
				long receiverDepositNumber = transactionSelected
						.getReceiverID();
				receiver = depositAccountService
						.getDepositAccountByDepositAccountID(receiverDepositNumber);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return receiver;
	}

	public Customer getSenderCustomer() {
		try {
			long customerID = getSender().getCustomerID();
			Customer cus = accountService.getCustomerByID(customerID);
			return cus;
		} catch (Exception ex) {
			return null;
		}
	}

	public Customer getReceiverCustomer() {
		try {
			long customerID = getReceiver().getCustomerID();
			Customer cus = accountService.getCustomerByID(customerID);
			return cus;
		} catch (Exception ex) {
			return null;
		}
	}

	public DepositTransaction getTransactionSelected() {
		return transactionSelected;
	}

	public DepositTransaction getTransactionRelated() {
		return transactionRelated;
	}

	public List<DepositTransaction> getListPendingTransactions() {
		searchListPendingTransactions();
		return listPendingTransactions;
	}

	public String searchListPendingTransactions() {
		try {
			listPendingTransactions = depositAccountTransactionService
					.getDepositTransactionByState(TransactionState.HOLD);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "listTransactionPending";
	}

	public String reviewDepositTransaction(long depositTransactionID) {

		try {
			transactionSelected = depositAccountTransactionService
					.getTransactionByID(depositTransactionID);
			TransactionType transactionselectedType = transactionSelected
					.getTransactionType();
			if ((transactionselectedType.equals(TransactionType.RECEIVE))
					|| (transactionselectedType
							.equals(TransactionType.TRANSFER))) {
				transactionRelated = depositAccountTransactionService
						.getTransactionByID(transactionSelected
								.getRelatedTransaction());
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			transactionSelected = null;
			transactionRelated = null;
		}
		return "transactionReview";
	}

	public String approveDepositTransaction(long depositTransactionID) {
		this.transactionSelected = depositAccountTransactionService
				.getTransactionByID(depositTransactionID);
		if (transactionSelected.getTransactionState() != TransactionState.HOLD) {
			listPendingTransactions.remove(transactionSelected);
			return searchListPendingTransactions();
		}
		if (transactionSelected != null) {
			switch (transactionSelected.getTransactionType()) {
			case DEPOSIT:
				CustomerAccount account = depositAccountService
						.getDepositAccountByDepositAccountID(transactionSelected
								.getDepositAccountNumber());
				boolean result = depositAccountTransactionService
						.approveAddFunds(transactionSelected, account, 30000L);
				if (result) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}
			case WITHDRAW:

				boolean result2 = depositAccountTransactionService
						.approveWithdrawFunds(transactionSelected, 30000L);
				if (result2) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}
			case TRANSFER:
				CustomerAccount receiver = depositAccountService
						.getDepositAccountByDepositAccountID(transactionSelected
								.getReceiverID());
				if (depositAccountTransactionService.approveTransferFunds(
						transactionSelected, receiver, 30000L)) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}

			default:
				break;
			}
		}
		return "";
	}

	public String denyDepositTransaction(long depositTransactionID) {
		this.transactionSelected = depositAccountTransactionService
				.getTransactionByID(depositTransactionID);
		if (transactionSelected.getTransactionState() != TransactionState.HOLD) {
			listPendingTransactions.remove(transactionSelected);
			return searchListPendingTransactions();
		}
		if (transactionSelected != null) {
			switch (transactionSelected.getTransactionType()) {
			case DEPOSIT:
				boolean result = depositAccountTransactionService.denyAddFunds(
						transactionSelected, 30000L);
				if (result) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}
			case WITHDRAW:
				CustomerAccount account = depositAccountService
						.getDepositAccountByDepositAccountID(transactionSelected
								.getDepositAccountNumber());
				boolean result2 = depositAccountTransactionService
						.denyWithdrawFunds(transactionSelected, account, 30000L);
				if (result2) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}
			case TRANSFER:
				CustomerAccount sender = depositAccountService
						.getDepositAccountByDepositAccountID(transactionSelected
								.getSenderID());
				if (depositAccountTransactionService.denyTransferFunds(
						transactionSelected, sender, 30000L)) {
					listPendingTransactions.remove(transactionSelected);
					return "listTransactionPending";
				} else {
					FacesContext.getCurrentInstance().addMessage(null,
							new FacesMessage("Error! Please try again!"));
					return "";
				}

			default:
				break;
			}
		}
		return "";
	}

	public SystemUser getSystemUser() {
		return systemUser;
	}

	public void setSystemUser(SystemUser systemUser) {
		this.systemUser = systemUser;
	}
}
